import random, queue
import time
from multiprocessing.dummy import freeze_support
from multiprocessing.managers import BaseManager

"""
python 可以基于multiprocessing快速实现分布式通过队列交换数据，manager底层可以对外暴漏网络接口
"""

task_q = queue.Queue()
task_result_q = queue.Queue()


# 定义一个队列管理器
class QManager(BaseManager):
    pass


def get_task():
    global task_q  # 很奇怪，不声明为global, slave收不到。。。
    return task_q


def get_result():
    global task_result_q
    return task_result_q


if __name__ == '__main__':
    # Windows下多进程可能出现问题，添加以下代码可以缓解
    freeze_support()
    # 队列注册到网络，这个manager相当于一个broker
    QManager.register('get_task', callable=get_task)
    QManager.register('get_result', callable=get_result)

    # 初始化队列管理器，并指定暴漏地址和连接验证key，就是密码
    m = QManager(address=('localhost', 13258), authkey=b'hello')
    m.start()  # 启动，必须放到__main__中执行，需要启动一个子进程，但是紫禁城必须要在主进程main调用main后才行，放到__main__上面全局不可以

    # 通过manager获取到队列，不能直接使用上面queue.Queue()创建的队列，那个是本地的，并不是网络暴露的
    net_task_q: queue.Queue = m.get_task()

    for i in range(10):
        print(f'Put task: {i}')
        time.sleep(2)
        net_task_q.put(random.randint(0, 100))

    print('Ready get result...')
    # 获取结果集队列
    net_task_result_q: queue.Queue = m.get_result()
    for i in range(10):
        print(f'Get result: {net_task_result_q.get(timeout=30)}')

    print('Shutdown manager')
    m.shutdown()  # 关闭manager